package com.java.thread;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 日期工具类:
 * 1.要提供一个将字符串转换为日期对象的方法
 * 2.要保证其线程安全和效率
 */
class DateUtil1{
      //SimpleDateFormat是一个线程不安全对象,不允许多线程并发访问.
      //static SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
     //如何保证一个线程一个SimpleDateFormat对象呢? 可以通过ThreadLocal实现
     private static ThreadLocal<SimpleDateFormat> tl=new ThreadLocal<>();
     private static AtomicLong atomicLong=new AtomicLong(1);
     public static Date parseStr(String dateStr)throws ParseException{
          //获取当前线程绑定的对象
          SimpleDateFormat sdf=tl.get();//这里的get是要从线程对象的ThreadlocalMap中取值,默认key为threadlocal
          //假如当前线程没有sdf对象则创建,然后将创建的对象存储到当前线程的map中
          if(sdf==null){
              System.out.println("create->"+atomicLong.getAndIncrement());
              sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
              //存储到当前线程的map中
              tl.set(sdf);//key是谁?value是谁?
          }
          //每次调用parseStr方法,此对象要创建,能否减少其创建次数
          //SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
          return sdf.parse(dateStr);
     }
     public static void remove(){
         tl.remove();
     }
}

class DateUtil2{

    private static ThreadLocal<SimpleDateFormat> tl=new ThreadLocal<SimpleDateFormat>(){
        @Override
        protected SimpleDateFormat initialValue() {
            return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        }
    };
    public static Date parseStr(String dateStr)throws ParseException{
        SimpleDateFormat sdf=tl.get();
        return sdf.parse(dateStr);
    }
}


public class ThreadLocalTests {

    public static void main(String[] args) {
        for(int i=0;i<10;i++) {
            new Thread(()->{
                for(int j=0;j<5;j++) {
                    String dateStr = "2023-10-24 15:23:12";
                    try {
                        System.out.println(DateUtil1.parseStr(dateStr));
                    } catch (ParseException e) {
                    }
                }
                DateUtil1.remove();//防止内存泄漏
            }).start();
        }
    }
}
